package beans;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * MVC : most valuable class<br/>
 * 分析Map。
 * 
 * HashMap Hashtable LinkedHashMap 和 TreeMap<br/>
 * 
 * 1.HashMap不支持线程的同步，如果需要同步，可以用 Collections的synchronizedMap方法使HashMap具有同步的能力，或者使用ConcurrentHashMaps<br/>
 * 2.Hashtable与 HashMap类似,它继承自Dictionary类，不同的是:它不允许记录的键或者值为空;它支持线程的同步，即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢<br/>
 * 3.LinkedHashMap 是HashMap的一个子类，保存了记录的插入顺序<br/>
 * 4.TreeMap实现SortMap接口，能够把它保存的记录根据键排序,默认是按键值的升序排序，也可以指定排序的比较器<br/>
 * 
 * @author Jert
 * 
 */
public class MapMVCDemo
{

	@SuppressWarnings("unchecked")
	public static void main(String[] args)
	{
		Map<String, String> linkedmap = new LinkedHashMap<String, String>();
		linkedmap.put("1", "aaa");
		linkedmap.put("2", "bbb");
		linkedmap.put("3", "ccc");

		Map<String, String> hashmap = new HashMap<String, String>();
		hashmap.put("1", "aaa");
		hashmap.put("2", "bbb");
		hashmap.put("3", "ccc");

		System.out.println();
		mainTestKetSet(linkedmap, hashmap);
		System.out.println();
		mainTestEntrySet(linkedmap, hashmap);
		System.out.println();

		mainTestSortedHashtable();
	}

	public static void mainTestSortedHashtable()
	{
		Hashtable<String, String> hashtable = new Hashtable<String, String>();
		hashtable.put("3", "ccc");
		hashtable.put("1", "aaa");
		hashtable.put("5", "eee");
		hashtable.put("2", "bbb");
		hashtable.put("4", "ddd");
		testSortedHashtable(hashtable);
	}

	public static void mainTestEntrySet(Map<String, String>... map)
	{
		testEntrySet(map[0]);
		testEntrySet(map[1]);
	}

	public static void mainTestKetSet(Map<String, String>... map)
	{
		testKetSet(map[0]);
		testKetSet(map[1]);
	}

	/**
	 * 标准的Map访问方法
	 * 
	 * 缺点：从Map中取得关键字之后，我们必须每次重复返回到Map中取得相对的值，这是很繁琐和费时的。
	 * 
	 * @param map
	 */
	private static void testKetSet(Map<String, String> map)
	{
		Set<String> keys = map.keySet();
		if (keys != null)
		{
			Iterator<String> iterator = keys.iterator();
			while (iterator.hasNext())
			{
				Object key = iterator.next();
				Object value = map.get(key);
				System.out.println(format(key, value));
			}
		}

	}

	/**
	 * entrySet()较keySet()标准的Map访问方式更加符合逻辑<br/>
	 * 
	 * 优点：弥补了keySet()的缺点，Map.Entry类提供了一个getKey()方法和一个getValue()方法，因此，上面的代码可以被组织得更符合逻辑。<br/>
	 * 尽管增加了一行代码，我们却省略了许多对Map不必要的“get”调用。同时，提供给开发人员一个同时保持了关键字和其对应的值的类。Map.Entry同时也提供了一个setValue()方法，程序员可以使用它修改map里面的值.
	 * 
	 * @param map
	 */
	private static void testEntrySet(Map<String, String> map)
	{
		Set<Entry<String, String>> entrys = map.entrySet();
		if (entrys != null)
		{
			Iterator<Entry<String, String>> iterator = entrys.iterator();
			while (iterator.hasNext())
			{
				Entry<String, String> entry = iterator.next();
				Object key = entry.getKey();
				Object value = entry.getValue();
				System.out.println(format(key, value));
			}

		}
	}

	/**
	 * Hashtable内部排列的方式是散列排布，所以当输出信息时会是无序的。为了能保证输出的数据按照顺序排列，不要渴望用java自带的函数来对Hashtable对象进行调整处理。当我们获取Hashtable里的KEY和VALUE时，
	 * 一般都运行了Map.Entry类来转换，好，现在就用这个类来作文章，我具体写了一个方法。
	 * 
	 * @param map
	 */
	private static void testSortedHashtable(Hashtable<String, String> hashtable)
	{
		Set<Entry<String, String>> set = hashtable.entrySet();

		@SuppressWarnings("unchecked")
		Entry<String, String>[] entries = set.toArray(new Entry[set.size()]);
		Arrays.sort(entries, new Comparator<Entry<String, String>>()
		{
			@Override
			public int compare(Entry<String, String> o1, Entry<String, String> o2)
			{
				Object key1 = o1.getKey();
				Object key2 = o2.getKey();

				return ((String) key1).compareTo((String) key2);
			}
		});

		for (Entry<String, String> entry : entries)
		{
			System.out.println(format(entry.getKey(), entry.getValue()));
		}
	}

	private static String format(Object key, Object value)
	{
		return "key = " + key.toString() + " || value = " + value.toString() + " ; ";
	}

}
